using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Xml;
using System.Xml.Serialization;
using Microsoft.SharePoint;
using DE.Sdc.SharePoint.SPContentStructure.Common;

namespace DE.Sdc.SharePoint.SPContentStructure.Import
{
    [Serializable]
    [XmlType(AnonymousType = true, Namespace = DeploymentConstants.Namespace)]
    [XmlRoot(Namespace = DeploymentConstants.Namespace, IsNullable = false)]
    public class ContentTypes : IImportDefinition<SPList, SPWeb>
    {
        public ContentTypes()
        {
            Items = new List<ContentType>();
        }

        [XmlAttribute]
        public bool RemoveExisting { get; set; }

        [XmlElement("ContentType")]
        public List<ContentType> Items { get; set; }

        [XmlIgnore]
        public SPList UpdatedSPObject { get; internal set; }

        /// <summary>
        /// Adds, modifies or deletes content types for a list
        /// </summary>
        /// <param name="list">A content type list based on the content type definition in a list or null</param>
        /// <param name="parentWeb">The parent list where to add, modify or delete the content types</param>
        public void ImportDefinition(SPList list, SPWeb parentWeb)
        {
            Trace.WriteLine(
                "Try to modify content types for list '" + list.Title + "' with url '" +
                list.RootFolder.ServerRelativeUrl + "'.", "ContentStructureImporter:ModifyContentTypes");


            // Removes all exisiting content types in the list, excluded this ones who are in use.
            if (RemoveExisting)
            {
                var contentTyppesToBeAdded = (from contentTypeDefinition in Items
                                              let contentTypeId =
                                                  DeploymentHelper.Resolve(contentTypeDefinition.Id, parentWeb.Locale)
                                              let contentType =
                                                  contentTypeDefinition.IdQualifier == QualifierType.Id
                                                      ? parentWeb.AvailableContentTypes[
                                                          new SPContentTypeId(contentTypeId)]
                                                      : parentWeb.AvailableContentTypes[contentTypeId]
                                              where
                                                  contentType != null && contentTypeDefinition.Action == ActionType.AddOrUpdate
                                              select contentType.Name).ToList();

                for (int index = 0; index < list.ContentTypes.Count; index++)
                {
                    SPContentType contentType = list.ContentTypes[index];
                    if (!contentTyppesToBeAdded.Contains(contentType.Name))
                    {
                        try
                        {
                            list.ContentTypes.Delete(contentType.Id);
                            index--;
                        }
                        catch
                        {
                            // ContentType could not be deleted, because it is in use.}
                        }
                    }
                }
            }

            if (Items.Count > 0)
            {
                list.ContentTypesEnabled = true;

                for (int index = 0; index < Items.Count; index++)
                {
                    ContentType contentTypeDefinition = Items[index];

                    contentTypeDefinition.Id = DeploymentHelper.Resolve(contentTypeDefinition.Id, parentWeb.Locale);
                    SPContentType contentType = contentTypeDefinition.IdQualifier == QualifierType.Id
                                                    ? parentWeb.AvailableContentTypes[
                                                        new SPContentTypeId(contentTypeDefinition.Id)]
                                                    : parentWeb.AvailableContentTypes[contentTypeDefinition.Id];

                    contentTypeDefinition.ImportDefinition(contentType, list);
                }
            }

            Trace.WriteLine(
                "Content types for list '" + list.Title + "' with url '" + list.RootFolder.ServerRelativeUrl +
                "'. modified", "ModifyContentTypes:ModifyContentTypes");

            UpdatedSPObject = list;
        }
    }
}